<template>
  <div class="chat-container">
    <h1>在线聊天机器人</h1>
    <div class="chat-window" ref="chatWindow">
      <!-- 消息列表 -->
      <div v-for="(message, index) in messages" :key="index" :class="['message', message.role]">
        <div class="avatar">
          <img v-if="message.role === 'assistant'" src="../../public/root.jpg" alt="机器人头像" />
          <img v-else src="../../public/me.jpg" alt="我的头像" />
        </div>
        <div class="content">
          <div class="text">{{ message.content }}</div>
        </div>
      </div>

      <!-- 加载动画 -->
      <div v-if="isLoading" class="loading-spinner">
        <div class="spinner"></div>
      </div>
    </div>

    <!-- 输入框和发送按钮 -->
    <div class="input-area">
      <textarea
        v-model="inputMessage"
        placeholder="请输入消息"
        :disabled="isLoading"
        @keydown.enter="handleKeydown"
        @input="adjustTextareaHeight"
        ref="inputArea"
        :style="{ height: textareaHeight + 'px' }"
      ></textarea>
      <button @click="sendMessage" :disabled="isLoading || !inputMessage.trim()">
        {{ isLoading ? '发送中...' : '发送' }}
      </button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick } from 'vue';

// 从 localStorage 中读取消息记录
const loadMessages = () => {
  const savedMessages = localStorage.getItem('chatMessages');
  return savedMessages ? JSON.parse(savedMessages) : [];
};

// 保存消息到 localStorage
const saveMessages = (messages) => {
  localStorage.setItem('chatMessages', JSON.stringify(messages));
};

const messages = ref(loadMessages()); // 初始化消息列表
const inputMessage = ref(''); // 输入框内容
const isLoading = ref(false); // 是否正在加载
const chatWindow = ref(null); // 聊天窗口的引用
const inputArea = ref(null); // 输入框的引用
const textareaHeight = ref(40); // 输入框的初始高度

// 发送消息
const sendMessage = async () => {
  if (isLoading.value || !inputMessage.value.trim()) return;

  try {
    // 添加用户消息
    messages.value.push({ role: 'user', content: inputMessage.value });
    saveMessages(messages.value); // 保存消息到 localStorage
    inputMessage.value = ''; // 清空输入框
    isLoading.value = true;

    // 请求配置
    const response = await fetch('https://api.deepseek.com/chat/completions', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: 'Bearer sk-35c769754041499381a92e5b0ab5dc95',
      },
      body: JSON.stringify({
        messages: [
          { content: 'You are a helpful assistant', role: 'system' },
          ...messages.value.map((msg) => ({ content: msg.content, role: msg.role })),
        ],
        model: 'deepseek-chat',
        stream: true,
        temperature: 1,
        max_tokens: 2048,
      }),
    });

    // 检查响应状态
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    // 创建流读取器
    const reader = response.body.getReader();
    const decoder = new TextDecoder();
    let assistantMessage = { role: 'assistant', content: '' }; // 初始化机器人消息

    // 递归读取流数据
    const readChunk = async () => {
      try {
        const { done, value } = await reader.read();
        if (done) {
          isLoading.value = false;
          return;
        }

        // 解码并处理数据块
        const chunk = decoder.decode(value);
        processChunk(chunk, assistantMessage);

        // 继续读取下一个数据块
        readChunk();
      } catch (error) {
        console.error('流读取错误:', error);
        isLoading.value = false;
      }
    };

    // 开始读取流
    readChunk();
  } catch (error) {
    console.error('请求失败:', error);
    isLoading.value = false;
  }
};

// 处理数据块的函数
const processChunk = (rawChunk, assistantMessage) => {
  const chunks = rawChunk.split('\n').filter((line) => line.trim());

  chunks.forEach((chunk) => {
    try {
      // 移除 "data: " 前缀
      const jsonStr = chunk.replace(/^data: /, '');
      if (jsonStr === '[DONE]') return;

      const data = JSON.parse(jsonStr);
      if (data.choices?.[0]?.delta?.content) {
        assistantMessage.content += data.choices[0].delta.content;

        // 更新消息列表
        const lastMessage = messages.value[messages.value.length - 1];
        if (lastMessage.role === 'assistant') {
          // 如果最后一条消息是机器人的消息，则更新内容
          lastMessage.content = assistantMessage.content;
        } else {
          // 否则创建一条新的机器人消息
          messages.value.push({ ...assistantMessage });
        }

        // 保存消息到 localStorage
        saveMessages(messages.value);

        // 滚动到底部
        scrollToBottom();
      }
    } catch (error) {
      console.error('JSON 解析错误:', error);
    }
  });
};

// 处理键盘事件
const handleKeydown = (event) => {
  if (event.key === 'Enter' && !event.shiftKey) {
    event.preventDefault(); // 阻止默认换行行为
    sendMessage();
  } else if (event.key === 'Enter' && event.shiftKey) {
    event.preventDefault(); // 阻止默认换行行为
    // 手动插入换行符
    const cursorPosition = inputArea.value.selectionStart;
    inputMessage.value =
      inputMessage.value.slice(0, cursorPosition) +
      '\n' +
      inputMessage.value.slice(cursorPosition);
    // 移动光标到新插入的换行符后
    nextTick(() => {
      inputArea.value.setSelectionRange(cursorPosition + 1, cursorPosition + 1);
    });
  }
};

// 动态调整输入框高度
const adjustTextareaHeight = () => {
  nextTick(() => {
    if (inputArea.value) {
      // 重置高度为 auto，以便计算正确的高度
      inputArea.value.style.height = 'auto';
      // 计算新的高度
      const newHeight = Math.min(inputArea.value.scrollHeight, 60); // 最大高度为 60px
      textareaHeight.value = newHeight;
    }
  });
};

// 滚动到底部
const scrollToBottom = () => {
  nextTick(() => {
    if (chatWindow.value) {
      chatWindow.value.scrollTop = chatWindow.value.scrollHeight;
    }
  });
};

// 组件挂载时加载消息记录并滚动到底部
onMounted(() => {
  messages.value = loadMessages();
  scrollToBottom();
});
</script>

<style scoped>
.chat-container {
  /* max-width: 1000px; */
  width: 1000px;
  margin: 0 auto;
  padding: 20px;
  font-family: Arial, sans-serif;
}

.chat-window {
  height: 500px;
  overflow-y: auto;
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 10px;
  background-color: #f9f9f9;
  margin-bottom: 20px;
  position: relative;
}

.message {
  display: flex;
  margin-bottom: 15px;
}

/* 左边消息（机器人） */
.message.assistant {
  justify-content: flex-start;
}

/* 右边消息（用户） */
.message.user {
  justify-content: flex-end;
}

/* 头像样式 */
.avatar {
  display: flex;
  align-items: flex-start; /* 头像靠上对齐 */
}

.avatar img {
  width: 40px;
  height: 40px;
  border-radius: 50%;
}

/* 消息内容样式 */
.content {
  max-width: 70%;
  margin-left: 10px;
  margin-right: 10px;
  padding: 10px;
  border-radius: 8px;
}

/* 用户消息背景色 */
.message.user .content {
  background-color: #4d6bfe;
  color: white;
  order: -1; /* 将消息内容放在头像的左边 */
}

/* 机器人消息背景色 */
.message.assistant .content {
  background-color: white;
  border: 1px solid #ddd;
}

/* 输入框和按钮区域 */
.input-area {
  display: flex;
  gap: 10px;
  align-items: flex-end; /* 按钮与输入框底部对齐 */
}

textarea {
  flex: 1;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 8px;
  font-size: 16px;
  resize: none; /* 禁止手动调整大小 */
  overflow-y: auto; /* 允许垂直滚动 */
  max-height: 200px; /* 最大高度 */
  line-height: 1.5; /* 行高 */
  background-color: #f5f5f5; /* 偏灰色背景 */
  transition: height 0.2s ease; /* 高度变化过渡效果 */
}

button {
  padding: 10px 20px;
  background-color: #4d6bfe;
  color: white;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  font-size: 16px;
}

button:disabled {
  opacity: 0.7;
  cursor: not-allowed;
}

/* 加载动画 */
.loading-spinner {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 10px;
}

.spinner {
  border: 4px solid #f3f3f3;
  border-top: 4px solid #4d6bfe;
  border-radius: 50%;
  width: 24px;
  height: 24px;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
</style>